#include "stdafx.h"
#include <codecvt>
#include <memory>
#include <string>
#include <sstream>
#include <iomanip>  
#include "Psapi.h"
#include "Global.h"
#include "Tlhelp32.h" 
#pragma comment (lib,"Psapi.lib")

namespace x_global
{
	unsigned char BCC_CheckSum(unsigned char *buf, unsigned char len)
	{
		unsigned char i;
		unsigned char checksum = 0;

		for (i = 0; i < len; i++) {
			checksum ^= *buf++;
		}

		return checksum;
	}

	void xDeleteDirectory(CString directory_path)   //Delete everything in a folder  
	{
		CFileFind finder;
		CString path;
		CString name = _T("");
		path.Format(_T("%s\\*.*"), directory_path);
		BOOL bWorking = finder.FindFile(path);
		while (bWorking)
		{
			bWorking = finder.FindNextFile();
			name = finder.GetFilePath();
			if (finder.IsSystem())
			{
				continue;
			}
			if (finder.IsDirectory() && !finder.IsDots()) {//Processing folder
				name = finder.GetFilePath();
				xDeleteDirectory(finder.GetFilePath()); //Delete folders recursively
				RemoveDirectory(finder.GetFilePath());
			}
			else {//settle documents
				name = finder.GetFilePath();
				DeleteFile(finder.GetFilePath());
			}
		}
	}

	std::string longTostring(unsigned long tmp)
	{
		std::ostringstream ss;
		ss << tmp;
		return ss.str();
	}

	std::string intTostring(int tmp)
	{
		std::ostringstream ss;
		ss << tmp;
		return ss.str();
	}

	std::string doubelTostring(double tmp)
	{
		std::ostringstream ss;
		ss << std::fixed << std::setprecision(6) << tmp;
		return ss.str();
	}

	CString stringToCString(std::string str)
	{
		return CString(str.c_str());
	}

	CString intToCString(const int num)
	{
		CString cstr;

		cstr.Format(_T("%d"), num);
		return cstr;
	}

	CString wstringTocstring(std::wstring str)
	{
		return stringToCString(wstringTostring(str));
	}

	std::wstring CStringToWstring(CString str)
	{
		return stringTowstring(cstringTostring(str));
	}


	std::string get_current_path()
	{
		TCHAR filePath[256];
		memset(filePath, 0x00, 256);
		::GetModuleFileName(nullptr, filePath, 255);
		CString strPathTmp;
		strPathTmp = filePath;
		int iPos = -1;
		strPathTmp.Replace(_T("\\"), _T("/"));
		iPos = strPathTmp.ReverseFind('/');
		if (iPos >= 0)
		{
			strPathTmp = strPathTmp.Mid(0, iPos + 1);
		}
		return std::string((LPCSTR)CStringA(strPathTmp));
	}

	std::string cstringTostring(CString str)
	{
		return std::string((LPCSTR)CStringA(str));
	}

	CString pcharTocstring(char *pChar)
	{
		int charLen = strlen(pChar); //Calculates the size of the string pChar points to, in bytes, one character for two bytes
		int len = MultiByteToWideChar(CP_ACP, 0, pChar, charLen, NULL, 0); //Calculates the size of a multi-byte character, calculated by character
		wchar_t *pWChar = new wchar_t[len + 1]; //Request space for wide byte characters, 
		MultiByteToWideChar(CP_ACP, 0, pChar, charLen, pWChar, len); //Converts a multi-byte code to a wide byte code
		pWChar[len] = '\0';

		//Convert wCHAR T array to CString
		CString str;
		str.Append(pWChar);

		delete[] pWChar;
		return str;
	}

	char* cstringTopchar(CString str)
	{
		return (char*)(cstringTostring(str).c_str());
	}

	std::wstring stringTowstring(std::string str)
	{
		int nLen = (int)str.length();
		std::wstring wstr;
		wstr.resize(nLen, L' ');
		
		int nResult = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)str.c_str(), nLen, (LPWSTR)wstr.c_str(), nLen);
		
		if (nResult == 0)
		{
			return L"";
		}
		
		return wstr;

		//The following code cannot handle Chinese characters
		/*typedef std::codecvt_utf8<wchar_t> convert_type;
		std::wstring_convert<convert_type, wchar_t> converter;

		//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
		std::wstring converted_str = converter.from_bytes(str);

		return converted_str;*/
	}

	std::string wstringTostring(std::wstring str)
	{
		typedef std::codecvt_utf8<wchar_t> convert_type;
		std::wstring_convert<convert_type, wchar_t> converter;

		//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
		std::string converted_str = converter.to_bytes(str);

		return converted_str;

	}

	CString GetXCurrentTime(BOOL bFile)
	{
		SYSTEMTIME st;

		CString strTime;

		GetLocalTime(&st);
		if (!bFile)
		{
			strTime.Format(_T("%04d-%02d-%02d %02d:%02d:%02d"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);


		}
		else
		{
			strTime.Format(_T("_%04d%02d%02d%02d%02d%02d"), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
		}
		return strTime;
	}

	CString GetCurrentPath()
	{
		TCHAR filePath[256];
		memset(filePath, 0x00, 256);
		::GetModuleFileName(nullptr, filePath, 255);
		CString strPathTmp;
		strPathTmp = filePath;
		int iPos = -1;
		strPathTmp.Replace(_T("\\"), _T("/"));
		iPos = strPathTmp.ReverseFind('/');
		if (iPos >= 0)
		{
			strPathTmp = strPathTmp.Mid(0, iPos + 1);
		}
		return strPathTmp;

	}

	BOOL WStringToString(const std::wstring &wstr, std::string &str)
	{
		int nLen = (int)wstr.length();
		str.resize(nLen, ' ');

		int nResult = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)wstr.c_str(), nLen, (LPSTR)str.c_str(), nLen, NULL, NULL);

		if (nResult == 0)
		{
			return FALSE;
		}

		return TRUE;
	}

	int GetProcessCount(const TCHAR * szExeName)
	{
		HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		CString strName;
		int count = 0;
		if (hProcessSnap == FALSE)
		{
			printf("CreateToolhelp32Snapshot error");
			return -1;
		}
		PROCESSENTRY32 pe32;
		pe32.dwSize = sizeof(PROCESSENTRY32);

		BOOL bRet = Process32First(hProcessSnap, &pe32);
		while (bRet)
		{
			strName.Format(_T("%s"), pe32.szExeFile);
			if (strName == CString(szExeName))
			{
				count++;
			}
			//printf("[PID]:%d\n\n",pe32.th32ProcessID);
			bRet = Process32Next(hProcessSnap, &pe32);
		}
		::CloseHandle(hProcessSnap); // Often forget this sentence
		return count;
	}

	void chr2wch(const char* buffer, wchar_t* wBuf)
	{
		size_t len = strlen(buffer);
		size_t wlen = MultiByteToWideChar(CP_ACP, 0, (const char*)buffer, int(len), NULL, 0);
		wBuf = new wchar_t[wlen + 1];
		MultiByteToWideChar(CP_ACP, 0, (const char*)buffer, int(len), wBuf, int(wlen));
	}

	int KillOldProcess(LPCTSTR strProcessName)
	{
		if (NULL == strProcessName)
		{
			return FALSE;
		}
		HANDLE handle32Snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if (INVALID_HANDLE_VALUE == handle32Snapshot)
		{
			return FALSE;
		}

		PROCESSENTRY32 pEntry;
		pEntry.dwSize = sizeof(PROCESSENTRY32);

		//Search for all the process and terminate it
		if (Process32First(handle32Snapshot, &pEntry))
		{
			BOOL bFound = FALSE;
			if (!_tcsicmp(pEntry.szExeFile, strProcessName))
			{
				bFound = TRUE;
			}
			while ((!bFound) && Process32Next(handle32Snapshot, &pEntry))
			{
				if (!_tcsicmp(pEntry.szExeFile, strProcessName))
				{
					bFound = TRUE;
				}
			}
			if (bFound)
			{
				CloseHandle(handle32Snapshot);
				HANDLE handLe = OpenProcess(PROCESS_TERMINATE, FALSE, pEntry.th32ProcessID);
				BOOL bResult = TerminateProcess(handLe, 0);
				return bResult;
			}
		}

		CloseHandle(handle32Snapshot);
		return FALSE;
	}


	BOOL FolderExists(CString s)
	{
		DWORD attr;
		attr = GetFileAttributes(s);
		return (attr != (DWORD)(-1)) &&
			(attr & FILE_ATTRIBUTE_DIRECTORY);
	}
	// A unique application object
	BOOL CreateMuliteDirectory(CString P)
	{
		int len = P.GetLength();
		if (len <2) return false;
		if ('\\' == P[len - 1])
		{
			P = P.Left(len - 1);
			len = P.GetLength();
		}
		if (len <= 0) return false;
		if (len <= 3)
		{
			if (FolderExists(P))return true;
			else return false;
		}
		if (FolderExists(P))return true;
		CString Parent;
		Parent = P.Left(P.ReverseFind('\\'));
		if (Parent.GetLength() <= 0)return false;
		BOOL Ret = CreateMuliteDirectory(Parent);
		if (Ret)
		{
			SECURITY_ATTRIBUTES sa;
			sa.nLength = sizeof(SECURITY_ATTRIBUTES);
			sa.lpSecurityDescriptor = NULL;
			sa.bInheritHandle = 0;
			Ret = (CreateDirectory(P, &sa) == TRUE);
			return Ret;
		}
		else
			return FALSE;
	}

	void GB2312_UTF8(char* source, char* dest)
	{
		TCHAR t_str[1024];

		int len = MultiByteToWideChar(CP_ACP, 0, source, -1, NULL, 0);
		MultiByteToWideChar(CP_ACP, 0, source, -1, t_str, len);
		t_str[len] = 0x00;

		len = WideCharToMultiByte(CP_UTF8, 0, t_str, -1, NULL, 0, NULL, NULL);
		WideCharToMultiByte(CP_UTF8, 0, t_str, -1, dest, len, NULL, NULL);
		dest[len] = 0x00;
	}

	// change the utf8 to unicode format
	void UTF_8ToUnicode(WCHAR * pOut, char * pText)
	{
		char * Uchar = (char *)pOut;
		Uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
		Uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
		return;
	}
	// change unicode to GB2312 format
	void UnicodeToGB2312(char * pOut, unsigned short uData)
	{
		WideCharToMultiByte(CP_ACP, NULL, (LPCWSTR)&uData, 1, pOut, sizeof(WCHAR), NULL, NULL);
		return;
	}

	TCHAR* UTF_8ToGB2312(TCHAR *&pOut, std::string uu)
	{
		char szTemp[500];
		memset(szTemp, 0, sizeof(szTemp));
		memcpy(szTemp, uu.c_str(), uu.length());
		UTF_8ToGB2312(pOut, szTemp, strlen(szTemp));
		return pOut;
	}

	// change utf8 to gb2312 format
	void UTF_8ToGB2312(TCHAR *pOut, char * pText, int pLen)
	{
		char * newBuf = new char[pLen + 1];
		memset(newBuf, 0x00, pLen + 1);
		char Ctemp[4];
		memset(Ctemp, 0, 4);

		int i = 0;
		int j = 0;

		while (i < pLen)
		{
			if (pText[i] > 0)
			{
				newBuf[j++] = pText[i++];
			}
			else
			{
				WCHAR Wtemp;
				UTF_8ToUnicode(&Wtemp, pText + i);
				UnicodeToGB2312(Ctemp, Wtemp);
				newBuf[j] = Ctemp[0];
				newBuf[j + 1] = Ctemp[1];
				i += 3;
				j += 2;
			}
		}
		newBuf[j] = '\0';
		MultiByteToWideChar(CP_ACP, 0, newBuf, -1, pOut, 100);
		delete[] newBuf;
		return;
	}

	CString GB2312_UTF8(CString src)
	{
		USES_CONVERSION;
		char * pFileName = T2A(src);
		char name[2048];
		ZeroMemory(name, 2048);
		GB2312_UTF8(pFileName, name);
		return A2T(name);
	}

	GUID CreateGuid()
	{
		GUID guid;
		CoCreateGuid(&guid);
		return guid;
	}

	std::string GuidTostring(const GUID& guid)
	{
		char buf[64] = { 0 };
		_snprintf_s(buf,
			sizeof(buf),
			"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
			guid.Data1, guid.Data2, guid.Data3,
			guid.Data4[0], guid.Data4[1],
			guid.Data4[2], guid.Data4[3],
			guid.Data4[4], guid.Data4[5],
			guid.Data4[6], guid.Data4[7]);
		return std::string(buf);
	}

}

